/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.tidal;

import argtrust.measure.LevelMeasure;
import argtrust.measure.Measure;
import java.util.Map;
import java.util.LinkedHashMap;
import argtrust.measure.LevelMeasureOperators;
import argtrust.measure.IMeasureOperators;
import argtrust.trustnet.Agent;
import argtrust.trustnet.AgentPair;
import argtrust.trustnet.ITrustSemantics;
import argtrust.trustnet.IndirectTrust;
import argtrust.trustnet.Trust;
import argtrust.trustnet.TrustLink;
import argtrust.trustnet.TrustNet;
import argtrust.trustnet.TrustNode;

/**
 *
 * @author Yuqing Tang
 */
public class TidalTrust implements ITrustSemantics {

    Map<AgentPair, Measure> mTrustTable = new LinkedHashMap<AgentPair, Measure>();
    TrustNet mTrustnet;
    //thredshould
    double mTheta = 0;
    LevelMeasureOperators mComparator = new LevelMeasureOperators();

    public IMeasureOperators getOperators() {
        return mComparator;
    }

    public TidalTrust(TrustNet trust_net, double threshold) {
        mTrustnet = trust_net;
        mTheta = threshold;
    }

    double trustLevel(Measure measure) {
        if (measure.getOpMeasure() instanceof LevelMeasure) {
            return ((LevelMeasure) measure.getOpMeasure()).getLevel();
        } else {
            //TODO: throw exception
            System.err.println("TidalTrust is having trouble in getting trust level");
            if (measure != null) {
                System.err.println("Measure type: " + measure.getClass().getName());
            }
            return 0;
        }
    }

    public double trustLevel(Agent agent, Agent other) {
        return trustLevel(trust(agent, other));

    }

    public Measure trust(Agent agent, Agent other) {
        AgentPair edge = new AgentPair(agent, other);
        Measure res = mTrustTable.get(edge);
        if (res == null) {
            TrustNode trust_node = mTrustnet.getTrustNode(agent);
            double numerator = 0;
            double denominator = 0;
            for (TrustLink trust_link : trust_node.getTrustLinkList()) {
                Trust tr = trust_link.getTrust();
                if (tr.getTail().equals(other)) {

                    res = new LevelMeasure((LevelMeasure) tr.getMeasure());
                    mTrustTable.put(edge, res);
                    return res;
                }
                double tr_level = trustLevel(tr.getMeasure());
                if (tr_level >= mTheta) {
                    denominator += tr_level;
                    numerator += tr_level * trustLevel(trust(tr.getTail(), other));
                }
            }
            IndirectTrust ind_trust = new IndirectTrust();
            if (denominator != 0) {
                ind_trust.setMeasure(new LevelMeasure(numerator / denominator));
            } else {
                ind_trust.setMeasure(new LevelMeasure(0));

            }
            mTrustTable.put(edge, ind_trust);
            res = ind_trust;
        }
        return res;
    }
}
